home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)recvjob.c 5.6 (Berkeley) 5/5/88";
- #endif /* not lint */
-
- /*
- * Receive printer jobs from the network, queue them and
- * start the printer daemon.
- */
-
- #include "lp.h"
- #ifndef sprite
- #include <sys/fs.h>
- #endif
-
- char *sp = "";
- #define ack() (void) write(1, sp, 1);
-
- char tfname[40]; /* tmp copy of cf before linking */
- char dfname[40]; /* data files */
- int minfree; /* keep at least minfree blocks available */
- char *ddev; /* disk device (for checking free space) */
- int dfd; /* file system device descriptor */
-
- char *find_dev();
-
- recvjob()
- {
- struct stat stb;
- char *bp = pbuf;
- int status, rcleanup();
-
- /*
- * Perform lookup for printer name or abbreviation
- */
- if ((status = pgetent(line, printer)) < 0)
- frecverr("cannot open printer description file");
- else if (status == 0)
- frecverr("unknown printer %s", printer);
- if ((LF = pgetstr("lf", &bp)) == NULL)
- LF = DEFLOGF;
- if ((SD = pgetstr("sd", &bp)) == NULL)
- SD = DEFSPOOL;
- if ((LO = pgetstr("lo", &bp)) == NULL)
- LO = DEFLOCK;
-
- (void) close(2); /* set up log file */
- if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
- syslog(LOG_ERR, "%s: %m", LF);
- (void) open("/dev/null", O_WRONLY);
- }
-
- if (chdir(SD) < 0)
- frecverr("%s: %s: %m", printer, SD);
- if (stat(LO, &stb) == 0) {
- if (stb.st_mode & 010) {
- /* queue is disabled */
- putchar('\1'); /* return error code */
- exit(1);
- }
- } else if (stat(SD, &stb) < 0)
- frecverr("%s: %s: %m", printer, SD);
- #ifndef sprite
- minfree = read_number("minfree");
- ddev = find_dev(stb.st_dev, S_IFBLK);
- if ((dfd = open(ddev, O_RDONLY)) < 0)
- syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
- #else
- /*
- * Should have similar thing to check for free space...
- */
- #endif
- signal(SIGTERM, rcleanup);
- signal(SIGPIPE, rcleanup);
-
- if (readjob())
- printjob();
- }
-
- #ifndef sprite
- char *
- find_dev(dev, type)
- register dev_t dev;
- register int type;
- {
- register DIR *dfd = opendir("/dev");
- struct direct *dir;
- struct stat stb;
- char devname[MAXNAMLEN+6];
- char *dp;
-
- strcpy(devname, "/dev/");
- while ((dir = readdir(dfd))) {
- strcpy(devname + 5, dir->d_name);
- if (stat(devname, &stb))
- continue;
- if ((stb.st_mode & S_IFMT) != type)
- continue;
- if (dev == stb.st_rdev) {
- closedir(dfd);
- dp = (char *)malloc(strlen(devname)+1);
- strcpy(dp, devname);
- return(dp);
- }
- }
- closedir(dfd);
- frecverr("cannot find device %d, %d", major(dev), minor(dev));
- /*NOTREACHED*/
- }
- #endif /* sprite */
-
- /*
- * Read printer jobs sent by lpd and copy them to the spooling directory.
- * Return the number of jobs successfully transfered.
- */
- readjob()
- {
- register int size, nfiles;
- register char *cp;
-
- ack();
- nfiles = 0;
- for (;;) {
- /*
- * Read a command to tell us what to do
- */
- cp = line;
- do {
- if ((size = read(1, cp, 1)) != 1) {
- if (size < 0)
- frecverr("%s: Lost connection",printer);
- return(nfiles);
- }
- } while (*cp++ != '\n');
- *--cp = '\0';
- cp = line;
- switch (*cp++) {
- case '\1': /* cleanup because data sent was bad */
- rcleanup();
- continue;
-
- case '\2': /* read cf file */
- size = 0;
- while (*cp >= '0' && *cp <= '9')
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
- break;
- /*
- * host name has been authenticated, we use our
- * view of the host name since we may be passed
- * something different than what gethostbyaddr()
- * returns
- */
- strcpy(cp + 6, from);
- strcpy(tfname, cp);
- tfname[0] = 't';
- if (!chksize(size)) {
- (void) write(1, "\2", 1);
- continue;
- }
- if (!readfile(tfname, size)) {
- rcleanup();
- continue;
- }
- if (link(tfname, cp) < 0)
- frecverr("%s: %m", tfname);
- (void) unlink(tfname);
- tfname[0] = '\0';
- nfiles++;
- continue;
-
- case '\3': /* read df file */
- size = 0;
- while (*cp >= '0' && *cp <= '9')
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
- break;
- if (!chksize(size)) {
- (void) write(1, "\2", 1);
- continue;
- }
- strcpy(dfname, cp);
- (void) readfile(dfname, size);
- continue;
- }
- frecverr("protocol screwup");
- }
- }
-
- /*
- * Read files send by lpd and copy them to the spooling directory.
- */
- readfile(file, size)
- char *file;
- int size;
- {
- register char *cp;
- char buf[BUFSIZ];
- register int i, j, amt;
- int fd, err;
-
- fd = open(file, O_WRONLY|O_CREAT, FILMOD);
- if (fd < 0)
- frecverr("%s: %m", file);
- ack();
- err = 0;
- for (i = 0; i < size; i += BUFSIZ) {
- amt = BUFSIZ;
- cp = buf;
- if (i + amt > size)
- amt = size - i;
- do {
- j = read(1, cp, amt);
- if (j <= 0)
- frecverr("Lost connection");
- amt -= j;
- cp += j;
- } while (amt > 0);
- amt = BUFSIZ;
- if (i + amt > size)
- amt = size - i;
- if (write(fd, buf, amt) != amt) {
- err++;
- break;
- }
- }
- (void) close(fd);
- if (err)
- frecverr("%s: write error", file);
- if (noresponse()) { /* file sent had bad data in it */
- (void) unlink(file);
- return(0);
- }
- ack();
- return(1);
- }
-
- noresponse()
- {
- char resp;
-
- if (read(1, &resp, 1) != 1)
- frecverr("Lost connection");
- if (resp == '\0')
- return(0);
- return(1);
- }
-
- /*
- * Check to see if there is enough space on the disk for size bytes.
- * 1 == OK, 0 == Not OK.
- */
- chksize(size)
- int size;
- {
- #ifndef sprite
- struct stat stb;
- register char *ddev;
- int spacefree;
- struct fs fs;
-
- if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
- return(1);
- if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
- return(1);
- spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
- size = (size + 1023) / 1024;
- if (minfree + size > spacefree)
- return(0);
- #endif
- return(1);
- }
-
- read_number(fn)
- char *fn;
- {
- char lin[80];
- register FILE *fp;
-
- if ((fp = fopen(fn, "r")) == NULL)
- return (0);
- if (fgets(lin, 80, fp) == NULL) {
- fclose(fp);
- return (0);
- }
- fclose(fp);
- return (atoi(lin));
- }
-
- /*
- * Remove all the files associated with the current job being transfered.
- */
- rcleanup()
- {
-
- if (tfname[0])
- (void) unlink(tfname);
- if (dfname[0])
- do {
- do
- (void) unlink(dfname);
- while (dfname[2]-- != 'A');
- dfname[2] = 'z';
- } while (dfname[0]-- != 'd');
- dfname[0] = '\0';
- }
-
- frecverr(msg, a1, a2)
- char *msg;
- {
- rcleanup();
- syslog(LOG_ERR, msg, a1, a2);
- putchar('\1'); /* return error code */
- exit(1);
- }
-